import json
from _decimal import Decimal
from django.utils import timezone

from django.http import JsonResponse
from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection

from apps.goods.models import SKU
from apps.orders.models import OrderInfo, OrderGoods
from apps.users.models import Address
from meiduo_mall.utils.views import LoginRequiredJSONMixin
from django.db  import transaction

"""
结算订单接口文档：
    请求方式：　GET
    路由：     orders/settlement
    参数：     无
    响应结果：json   code errmsg  content  address, skus, freight,count
"""
class OrderSettlementView(LoginRequiredJSONMixin, View):
    def get(self, request):
        # 1.查询  当前用户的 所有地址(未删除)
        addresses = Address.objects.filter(user=request.user, is_deleted=False)

        # 2.查询  redis 购物车-selected=True
        carts_redis_client = get_redis_connection('carts')
        carts_data = carts_redis_client.hgetall(request.user.id)
        carts_dict = {}  # 购物车-selected=True
        for k, v in carts_data.items():
            sku_id = int(k.decode())
            sku_dict = json.loads(v.decode())

            if sku_dict['selected']:
                carts_dict[sku_id] = sku_dict

        # 3.根据 选中的商品id--SKU --sku
        sku_ids = carts_dict.keys()
        skus_list = []
        for sku_id in sku_ids:
            sku = SKU.objects.get(pk=sku_id)
            skus_list.append({
                'id': sku.id,
                'name': sku.name,
                'default_image_url': sku.default_image.url,
                'price': sku.price,
                'count': carts_dict[sku_id]['count']
            })

        # 4.数据格式装换
        address_list = []
        for address in addresses:
            address_list.append({
                "id": address.id,

                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,

                "place": address.place,
                "mobile": address.mobile,
                "receiver": address.receiver,
            })

        # 由于美多商城  只有自己的自营商品 B2C ; 统一运费  10.00
        freight = Decimal('10.00')

        context = {
            'skus': skus_list,
            'addresses': address_list,
            'freight': freight
        }

        return JsonResponse({'code': 0, 'errmsg': 'OK', 'context': context})


"""
提交订单接口文档：
    请求方式：　POST
    路由：　　　/orders/commit/
    参数： json     address_id   pay_method
    响应：json   code  errmsg  order_id
"""
class OrderCommitView(LoginRequiredJSONMixin, View):
    def post(self, request):
        # 1.接收参数
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')

        # 2.校验参数 -判空--address_id -pay_method
        if not all([address_id, pay_method]):
            return JsonResponse({'code': 400, 'errmsg': '参数不齐!'})

        try:
            address = Address.objects.get(pk=address_id)
        except Exception as e:
            return JsonResponse({'code': 400, 'errmsg': '地址不存在!'})

        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return JsonResponse({'code': 400, 'errmsg': '不支持这种支付方式!'})

        # 3.订单号的生成--时间+ 9个0 + user.id
        user = request.user
        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)

        # 创建事物
        with transaction.atomic():
            # 创建保存点
            save_id = transaction.savepoint()
            try:

                # 4.提交 订单的数据 OrderInfo.objects.create()
                order = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=address,
                    freight=Decimal('10.00'),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM['ALIPAY']
                    else OrderInfo.ORDER_STATUS_ENUM['UNSEND'],

                    total_count=0,
                    total_amount=Decimal('0.00')

                )

                print(order_id)
                # 5.取出购物车选中的商品
                carts_redis_client = get_redis_connection('carts')
                carts_data = carts_redis_client.hgetall(user.id)
                carts_dict = {}
                for k, v in carts_data.items():
                    sku_id = int(k.decode())
                    sku_dict = json.loads(v.decode())
                    if sku_dict['selected']:
                        carts_dict[sku_id] = sku_dict

                # 6.将商品 存入 订单商品表中--OrderGoods.objects.create()
                for sku_id in carts_dict.keys():

                    while True:
                        sku = SKU.objects.get(pk=sku_id)
                        cart_count = carts_dict[sku_id]['count']

                        # 获取老库存老销量
                        origin_stock = sku.stock
                        origin_sales = sku.sales

                        # 将购买的个数 和 stock库存比较
                        if cart_count > sku.stock:
                            # 事物回滚
                            transaction.savepoint_rollback(save_id)
                            return JsonResponse({'code': 400, 'errmsg': '库存不足!'})

                        # 加延迟是为了资源竞争
                        # import time
                        # time.sleep(10)

                        #  sku表 库存减少--
                        # sku.stock -= cart_count
                        # # # -销量增加
                        # sku.sales += cart_count
                        # sku.save()

                        # 计算新库存新销量
                        new_stock = origin_stock - cart_count
                        new_sales = origin_sales + cart_count
                        result = SKU.objects.filter(id=sku_id, stock=origin_stock).update(stock=new_stock,
                                                                                          sales=new_sales)
                        # 如果下单下单失败,库存足够则继续下单,直到下单成功或者库存不足
                        if result == 0:
                            continue

                        # spu表--销量增加
                        sku.spu.sales += cart_count
                        sku.spu.save()

                        OrderGoods.objects.create(
                            order=order,
                            sku=sku,
                            count=cart_count,
                            price=sku.price,
                        )
                        #  计算出 总金额 和 总个数
                        order.total_count += cart_count
                        order.total_amount += cart_count * sku.price

                        # 下单成功，跳出循环
                        break

                #  更新 订单表的订单数据
                order.total_amount += order.freight
                order.save()

            except Exception as e:
                # 事物回滚
                transaction.savepoint_rollback(save_id)
                return JsonResponse({'code': 0, 'errmsg': '下单失败'})

            # 事物提交
            transaction.savepoint_commit(save_id)


        # 删除购物车选中的商品
        # for sku_id in carts_dict:
        #     carts_redis_client.hdel(user.id, sku_id)

        # 返回响应对象
        return JsonResponse({'code': 0, 'errmsg': 'OK', 'order_id': order.order_id})
















